home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / wais / waisgate / HTAccess.c < prev    next >
C/C++ Source or Header  |  1995-05-09  |  16KB  |  630 lines

  1. /*        Access Manager                    HTAccess.c
  2. **        ==============
  3. **
  4. ** Authors
  5. **    TBL    Tim Berners-Lee timbl@info.cern.ch
  6. **    JFG    Jean-Francois Groff jfg@dxcern.cern.ch
  7. **    DD    Denis DeLaRoca (310) 825-4580  <CSP1DWD@mvs.oac.ucla.edu>
  8. ** History
  9. **       8 Jun 92 Telnet hopping prohibited as telnet is not secure TBL
  10. **    26 Jun 92 When over DECnet, suppressed FTP, Gopher and News. JFG
  11. **     6 Oct 92 Moved HTClientHost and logfile into here. TBL
  12. **    17 Dec 92 Tn3270 added, bug fix. DD
  13. **     4 Feb 93 Access registration, Search escapes bad chars TBL
  14. **          PARAMETERS TO HTSEARCH AND HTLOAFRELATIVE CHANGED
  15. **
  16. ** Bugs
  17. **    This module assumes that that the graphic object is hypertext, as it
  18. **    needs to select it when it has been loaded.  A supercalss needs to be
  19. **    defined which accepts select and select_anchor.
  20. */
  21.  
  22. /* Implements:
  23. */
  24. #include "HTAccess.h"
  25.  
  26. /* Uses:
  27. */
  28.  
  29. #include "HTParse.h"
  30. #include "HTUtils.h"
  31. #include "HTML.h"        /* SCW */
  32.  
  33. #ifndef NO_RULES
  34. #include "HTRules.h"
  35. #endif
  36.  
  37. #include <stdio.h>
  38.  
  39. #include "HTList.h"
  40. #include "HText.h"    /* See bugs above */
  41. #include "HTAlert.h"
  42.  
  43.  
  44. /*    These flags may be set to modify the operation of this module
  45. */
  46. PUBLIC char * HTClientHost = 0;    /* Name of remote login host if any */
  47. PUBLIC FILE * logfile = 0;    /* File to which to output one-liners */
  48.  
  49. /*    To generate other things, play with these:
  50. */
  51.  
  52. PUBLIC HTFormat HTOutputFormat = NULL;
  53. PUBLIC HTStream* HTOutputStream = NULL;    /* For non-interactive, set this */ 
  54.  
  55. PRIVATE HTList * protocols = NULL;   /* List of registered protocol descriptors */
  56.  
  57.  
  58. /*    Register a Protocol                HTRegisterProtocol
  59. **    -------------------
  60. */
  61.  
  62. PUBLIC BOOL HTRegisterProtocol(protocol)
  63.     HTProtocol * protocol;
  64. {
  65.     if (!protocols) protocols = HTList_new();
  66.     HTList_addObject(protocols, protocol);
  67.     return YES;
  68. }
  69.  
  70.  
  71. /*    Register all known protocols
  72. **    ----------------------------
  73. **
  74. **    Add to or subtract from this list if you add or remove protocol modules.
  75. **    This routine is called the first time the protocol list is needed,
  76. **    unless any protocols are already registered, in which case it is not called.
  77. **    Therefore the application can override this list.
  78. **
  79. **    Compiling with NO_INIT prevents all known protocols from being forced
  80. **    in at link time.
  81. */
  82.  
  83. /* for this waisgate, just register wais !! */
  84.  
  85. #ifndef NO_INIT
  86. PRIVATE void HTAccessInit NOARGS            /* Call me once */
  87. {
  88. extern HTProtocol HTWAIS;
  89.     HTRegisterProtocol(&HTWAIS);
  90. #if 0
  91. extern HTProtocol HTTP, HTFile, HTTelnet, HTTn3270, HTRlogin;
  92. extern HTProtocol HTFTP, HTNews, HTGopher;
  93.     HTRegisterProtocol(&HTFTP);
  94.     HTRegisterProtocol(&HTNews);
  95.     HTRegisterProtocol(&HTGopher);
  96.     HTRegisterProtocol(&HTTP);
  97.     HTRegisterProtocol(&HTFile);
  98.     HTRegisterProtocol(&HTTelnet);
  99.     HTRegisterProtocol(&HTTn3270);
  100.     HTRegisterProtocol(&HTRlogin);
  101. #endif
  102. }
  103. #endif
  104.  
  105.  
  106. /*        Find physical name and access protocol
  107. **        --------------------------------------
  108. **
  109. **
  110. ** On entry,
  111. **    addr        must point to the fully qualified hypertext reference.
  112. **    anchor        a pareent anchor with whose address is addr
  113. **
  114. ** On exit,
  115. **    returns        HT_NO_ACCESS        Error has occured.
  116. **            HT_OK            Success
  117. **
  118. */
  119. PRIVATE int get_physical ARGS3(
  120.     CONST char *,        addr,
  121.     HTParentAnchor *,    anchor,
  122.     HTStream *,             sink)
  123. {
  124.     char * access=0;    /* Name of access method */
  125.     char * physical = 0;
  126.     int i, n;
  127.     HTProtocol *p;
  128.  
  129. #ifndef NO_RULES
  130.     physical = HTTranslate(addr);
  131.     if (!physical) {
  132.     return HT_FORBIDDEN;
  133.     }
  134.     HTAnchor_setPhysical(anchor, physical);
  135.     free(physical);            /* free our copy */
  136. #else
  137.     HTAnchor_setPhysical(anchor, addr);
  138. #endif
  139.  
  140.     access =  HTParse(HTAnchor_physical(anchor),
  141.             "file:", PARSE_ACCESS);
  142.  
  143. /*    Check whether gateway access has been set up for this
  144. */
  145. #ifdef USE_GATEWAYS
  146.     {
  147.     char * gateway_parameter; 
  148.     char * gateway;
  149.     gateway_parameter = (char *)malloc(strlen(access)+20);
  150.     if (gateway_parameter == NULL) outofmem(__FILE__, "HTLoad");
  151.     strcpy(gateway_parameter, "WWW_");
  152.     strcat(gateway_parameter, access);
  153.     strcat(gateway_parameter, "_GATEWAY");
  154.     gateway = (char *)getenv(gateway_parameter); /* coerce for decstation */
  155.     free(gateway_parameter);
  156.     if (gateway) {
  157.         int status = HTLoadHTTP(addr, gateway, anchor,
  158.             HTOutputFormat ? HTOutputFormat : WWW_PRESENT, sink);
  159.         HTAlert("Cannot retrieve required information from gateway.");
  160.         free(access);
  161.         return status;
  162.     }
  163.     }
  164. #endif
  165.  
  166.  
  167.  
  168. /*    Search registered protocols to find suitable one
  169. */
  170.     {
  171. #ifndef NO_INIT
  172.         if (!protocols) HTAccessInit();
  173. #endif
  174.     n = HTList_count(protocols);
  175.     for (i=0; i<n; i++) {
  176.         p = HTList_objectAt(protocols, i);
  177.         if (strcmp(p->name, access)==0) {
  178.         HTAnchor_setProtocol(anchor, p);
  179.         free(access);
  180.         return (HT_OK);
  181.         }
  182.     }
  183.     }
  184.  
  185.     free(access);
  186.     return HT_NO_ACCESS;
  187. }
  188.  
  189. logit(int status, char *full_address) {     
  190. /*    Log the access if necessary
  191. */
  192.     if (logfile) {
  193.     time_t theTime;
  194.     time(&theTime);
  195.     fprintf(logfile, "%24.24s %s %s %s\n",
  196.         ctime(&theTime),
  197.         HTClientHost ? HTClientHost : "local",
  198.         status<0 ? "FAIL" : "GET",
  199.         full_address);
  200.     fflush(logfile);    /* Actually update it on disk */
  201.     if (TRACE) fprintf(stderr, "Log: %24.24s %s %s %s\n",
  202.         ctime(&theTime),
  203.         HTClientHost ? HTClientHost : "local",
  204.         status<0 ? "FAIL" : "GET",
  205.         full_address);
  206.     }
  207.     
  208. }
  209. /*        Load a document
  210. **        ---------------
  211. **
  212. **    This is an internal routine, which has an address AND a matching
  213. **    anchor.  (The public routines are called with one OR the other.)
  214. **
  215. ** On entry,
  216. **    addr        must point to the fully qualified hypertext reference.
  217. **    anchor        a pareent anchor with whose address is addr
  218. **
  219. ** On exit,
  220. **    returns        <0        Error has occured.
  221. **            HT_LOADED    Success
  222. **            HT_NO_DATA    Success, but no document loaded.
  223. **
  224. */
  225. PRIVATE int HTLoad ARGS4(
  226.     CONST char *,        addr,
  227.     HTParentAnchor *,    anchor,
  228.     HTFormat,        format_out,
  229.     HTStream *,        sink)
  230. {
  231.     HTProtocol* p;
  232.     int status = get_physical(addr, anchor, sink);
  233.     if (status == HT_FORBIDDEN) {
  234.     logit(status, addr); 
  235.         return HTLoadError(sink, 500, "Access forbidden by rule");
  236.     }
  237.     if (status < 0) return status;    /* Can't resolve or forbidden */
  238.     
  239.     p = HTAnchor_protocol(anchor);
  240.     return (*(p->load))(HTAnchor_physical(anchor),
  241.                 anchor, format_out, sink);
  242. }
  243.  
  244.  
  245. /*        Get a save stream for a document
  246. **        --------------------------------
  247. */
  248. PUBLIC HTStream *HTSaveStream ARGS1(HTParentAnchor *, anchor)
  249. {
  250.     HTProtocol * p = HTAnchor_protocol(anchor);
  251.     if (!p) return NULL;
  252.     
  253.     return (*p->saveStream)(anchor);
  254.     
  255. }
  256.  
  257.  
  258. /*        Load a document - with logging etc
  259. **        ----------------------------------
  260. **
  261. **    - Checks or documents already loaded
  262. **    - Logs the access
  263. **    - Allows stdin filter option
  264. **    - Trace ouput and error messages
  265. **
  266. **    On Entry,
  267. **      anchor        is the node_anchor for the document
  268. **        full_address      The address of the document to be accessed.
  269. **        filter            if YES, treat stdin as HTML
  270. **
  271. **    On Exit,
  272. **        returns    YES     Success in opening document
  273. **                   NO      Failure 
  274. **
  275. */
  276.  
  277. PRIVATE BOOL HTLoadDocument ARGS4(
  278.     CONST char *,        full_address,
  279.     HTParentAnchor *,    anchor,
  280.     HTFormat,        format_out,
  281.     HTStream*,        sink)
  282.  
  283. {
  284.     int            status;
  285.     HText *    text;
  286.  
  287.     if (TRACE) fprintf (stderr,
  288.       "HTAccess: loading document %s\n", full_address);
  289.  
  290.     if (text=(HText *)HTAnchor_document(anchor)) {    /* Already loaded */
  291.         if (TRACE) fprintf(stderr, "HTAccess: Document already in memory.\n");
  292.         HText_select(text);
  293.     return YES;
  294.     }
  295.     
  296.     status = HTLoad(full_address, anchor, format_out, sink);
  297.  
  298.     
  299. /*    Log the access if necessary
  300. */
  301.     if (logfile) {
  302.     time_t theTime;
  303.     time(&theTime);
  304.     fprintf(logfile, "%24.24s %s %s %s\n",
  305.         ctime(&theTime),
  306.         HTClientHost ? HTClientHost : "local",
  307.         status<0 ? "FAIL" : "GET",
  308.         full_address);
  309.     fflush(logfile);    /* Actually update it on disk */
  310.     if (TRACE) fprintf(stderr, "Log: %24.24s %s %s %s\n",
  311.         ctime(&theTime),
  312.         HTClientHost ? HTClientHost : "local",
  313.         status<0 ? "FAIL" : "GET",
  314.         full_address);
  315.     }
  316.     
  317.  
  318.     if (status == HT_LOADED) {
  319.     if (TRACE) {
  320.         fprintf(stderr, "HTAccess: `%s' has been accessed.\n",
  321.         full_address);
  322.     }
  323.     return YES;
  324.     }
  325.     
  326.     if (status == HT_NO_DATA) {
  327.     if (TRACE) {
  328.         fprintf(stderr, 
  329.         "HTAccess: `%s' has been accessed, No data left.\n",
  330.         full_address);
  331.     }
  332.     return NO;
  333.     }
  334.     
  335.     if (status<0) {              /* Failure in accessing a document */
  336. #ifdef CURSES
  337.         user_message("Can't access `%s'", full_address);
  338. #else
  339.     if (TRACE) fprintf(stderr, 
  340.         "HTAccess: Can't access `%s'\n", full_address);
  341. #endif
  342.     HTLoadError(sink, 500, "Unable to access document.");
  343.     return NO;
  344.     }
  345.     
  346.     fprintf(stderr,
  347.     "**** HTAccess: socket or file number returned by obsolete load routine!\n");
  348.     exit(-6996);
  349.  
  350. } /* HTLoadDocument */
  351.  
  352.  
  353.  
  354. /*        Load a document from absolute name
  355. **        ---------------
  356. **
  357. **    On Entry,
  358. **        addr     The absolute address of the document to be accessed.
  359. **
  360. **    On Exit,
  361. **        returns    YES     Success in opening document
  362. **                   NO      Failure 
  363. **
  364. **
  365. */
  366.  
  367. PUBLIC BOOL HTLoadAbsolute ARGS1(CONST char *,addr)
  368. {
  369.    return HTLoadDocument( addr,
  370.                HTAnchor_parent(HTAnchor_findAddress(addr)),
  371.                    HTOutputFormat ? HTOutputFormat : WWW_PRESENT,
  372.             HTOutputStream);
  373. }
  374.  
  375.  
  376. /*        Load a document from absolute name to stream
  377. **        --------------------------------------------
  378. **
  379. **    On Entry,
  380. **        addr     The absolute address of the document to be accessed.
  381. **        sink     if non-NULL, send data down this stream
  382. **
  383. **    On Exit,
  384. **        returns    YES     Success in opening document
  385. **                   NO      Failure 
  386. **
  387. **
  388. */
  389.  
  390. PUBLIC BOOL HTLoadToStream ARGS3(
  391.         CONST char *,    addr,
  392.         BOOL,         filter,
  393.         HTStream *,     sink)
  394. {
  395.    return HTLoadDocument(addr,
  396.                HTAnchor_parent(HTAnchor_findAddress(addr)),
  397.                    HTOutputFormat ? HTOutputFormat : WWW_PRESENT,
  398.             sink);
  399. }
  400.  
  401.  
  402.  
  403.  
  404. /*        Load a document from relative name
  405. **        ---------------
  406. **
  407. **    On Entry,
  408. **        relative_name     The relative address of the document
  409. **                  to be accessed.
  410. **
  411. **    On Exit,
  412. **        returns    YES     Success in opening document
  413. **                   NO      Failure 
  414. **
  415. **
  416. */
  417.  
  418. PUBLIC BOOL HTLoadRelative ARGS2(
  419.         CONST char *,        relative_name,
  420.         HTParentAnchor *,    here)
  421. {
  422.     char *         full_address = 0;
  423.     BOOL               result;
  424.     char *         mycopy = 0;
  425.     char *         stripped = 0;
  426.     char *        current_address =
  427.                     HTAnchor_address((HTAnchor*)here);
  428.  
  429.     StrAllocCopy(mycopy, relative_name);
  430.  
  431.     stripped = HTStrip(mycopy);
  432.     full_address = HTParse(stripped,
  433.                current_address,
  434.            PARSE_ACCESS|PARSE_HOST|PARSE_PATH|PARSE_PUNCTUATION);
  435.     result = HTLoadAbsolute(full_address);
  436.     free(full_address);
  437.     free(current_address);
  438.     free(mycopy);  /* Memory leak fixed 10/7/92 -- JFG */
  439.     return result;
  440. }
  441.  
  442.  
  443. /*        Load if necessary, and select an anchor
  444. **        --------------------------------------
  445. **
  446. **    On Entry,
  447. **        destination              The child or parenet anchor to be loaded.
  448. **
  449. **    On Exit,
  450. **        returns    YES     Success
  451. **                   NO      Failure 
  452. **
  453. */
  454.  
  455. PUBLIC BOOL HTLoadAnchor ARGS1(HTAnchor *,destination)
  456. {
  457.     HTParentAnchor * parent;
  458.     BOOL loaded = NO;
  459.     if (!destination) return NO;    /* No link */
  460.     
  461.     parent  = HTAnchor_parent(destination);
  462.     
  463.     if (HTAnchor_document(parent) == NULL) {    /* If not alread loaded */
  464.                             /* TBL 921202 */
  465.  
  466.         BOOL result;
  467.         char * address = HTAnchor_address((HTAnchor*) parent);
  468.     result = HTLoadDocument(address, parent,
  469.         HTOutputFormat ? HTOutputFormat : WWW_PRESENT,
  470.         HTOutputStream);
  471.     free(address);
  472.     if (!result) return NO;
  473.     loaded = YES;
  474.     }
  475.     
  476.     {
  477.     HText *text = (HText*)HTAnchor_document(parent);
  478.     if (destination != (HTAnchor *)parent) {  /* If child anchor */
  479.         HText_selectAnchor(text, 
  480.             (HTChildAnchor*)destination); /* Double display? @@ */
  481.     } else {
  482.         if (!loaded) HText_select(text);
  483.     }
  484.     }
  485.     return YES;
  486.     
  487. } /* HTLoadAnchor */
  488.  
  489.  
  490. /*        Search
  491. **        ------
  492. **  Performs a keyword search on word given by the user. Adds the keyword to 
  493. **  the end of the current address and attempts to open the new address.
  494. **
  495. **  On Entry,
  496. **       *keywords      space-separated keyword list or similar search list
  497. **    here        is anchor search is to be done on.
  498. */
  499.  
  500. PRIVATE char hex(i)
  501.     int i;
  502. {
  503.     return i < 10 ? '0'+i : 'A'+ i - 10;
  504. }
  505.  
  506. PUBLIC BOOL HTSearch ARGS2(
  507.     CONST char *,         keywords,
  508.     HTParentAnchor *,     here)
  509. {
  510.  
  511. #define acceptable \
  512. "1234567890abcdefghijlkmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-_"
  513.  
  514.     char *q, *u;
  515.     CONST char * p, *s, *e;        /* Pointers into keywords */
  516.     char * address = HTAnchor_address((HTAnchor*)here);
  517.     BOOL result;
  518.     char * escaped = malloc(strlen(keywords)*3+1);
  519.  
  520.     static CONST BOOL isAcceptable[96] =
  521.  
  522.     /*   0 1 2 3 4 5 6 7 8 9 A B C D E F */
  523.     {    0,0,0,0,0,0,0,0,0,0,1,0,0,1,1,0,    /* 2x   !"#$%&'()*+,-./     */
  524.          1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,    /* 3x  0123456789:;<=>?     */
  525.      1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,    /* 4x  @ABCDEFGHIJKLMNO  */
  526.      1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,    /* 5X  PQRSTUVWXYZ[\]^_     */
  527.      0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,    /* 6x  `abcdefghijklmno     */
  528.      1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0 };    /* 7X  pqrstuvwxyz{\}~    DEL */
  529.  
  530.     if (escaped == NULL) outofmem(__FILE__, "HTSearch");
  531.     
  532.  
  533. /*    Convert spaces to + and hex escape unacceptable characters
  534. */
  535.     for(s=keywords; *s && WHITE(*s); s++) /*scan */ ;    /* Skip white space */
  536.     for(e = s + strlen(s); e>s && WHITE(*(e-1)) ; e--); /* Skip trailers */
  537.     for(q=escaped, p=s; p<e; p++) {            /* scan stripped field */
  538.         int c = (int)TOASCII(*p);
  539.         if (WHITE(*p)) {
  540.         *q++ = '+';
  541.     } else if (c>=32 && c<=(char)127 && isAcceptable[c-32]) {
  542.         *q++ = (char)c;
  543.     } else {
  544.         *q++ = '%';
  545.         *q++ = hex(c / 16);
  546.         *q++ = hex(c % 16);
  547.     }
  548.     } /* Loop over string */
  549.     
  550.     *q=0;
  551.                     /* terminate escaped sctring */
  552.     u=strchr(address, '?');        /* Find old search string */
  553.     if (u) *u = 0;                    /* Chop old search off */
  554.  
  555.     StrAllocCat(address, "?");
  556.     StrAllocCat(address, escaped);
  557.     free(escaped);
  558.     result = HTLoadRelative(address, here);
  559.     free(address);
  560.     
  561.     return result;
  562. }
  563.  
  564.  
  565. /*        Search Given Indexname
  566. **        ------
  567. **  Performs a keyword search on word given by the user. Adds the keyword to 
  568. **  the end of the current address and attempts to open the new address.
  569. **
  570. **  On Entry,
  571. **       *keywords      space-separated keyword list or similar search list
  572. **    *addres        is name of object search is to be done on.
  573. */
  574.  
  575. PUBLIC BOOL HTSearchAbsolute ARGS2(
  576.     CONST char *,     keywords,
  577.     CONST char *,     indexname)
  578. {
  579.     HTParentAnchor * anchor =
  580.         (HTParentAnchor*) HTAnchor_findAddress(indexname);
  581.     return HTSearch(keywords, anchor);
  582. }
  583.  
  584.  
  585. /*        Generate the anchor for the home page
  586. **        -------------------------------------
  587. **
  588. **    As it involves file access, this should only be done once
  589. **    when the program first runs.
  590. **    This is a default algorithm -- browesr don't HAVE to use this.
  591. **
  592. */
  593. PUBLIC HTParentAnchor * HTHomeAnchor NOARGS
  594. {
  595.     char * my_home = (char *)getenv(LOGICAL_DEFAULT);
  596.     BOOL got_local_default = NO;
  597.     char * ref;
  598.     HTParentAnchor * anchor;
  599.     
  600. #ifdef unix
  601.     {
  602.     FILE * fp = fopen(LOCAL_DEFAULT_FILE, "r");
  603.     if (fp) {
  604.         fclose(fp);
  605.         got_local_default = YES;
  606.     } else {
  607.     if (TRACE) fprintf(stderr,
  608.         "HTBrowse: No local default home %s\n",
  609.         LOCAL_DEFAULT_FILE);
  610.     }
  611.     }
  612. #endif
  613.     ref = HTParse( my_home ?    my_home :
  614.                 HTClientHost ? REMOTE_ADDRESS :
  615.                     got_local_default ? LOCAL_DEFAULT
  616.                         : LAST_RESORT,
  617.             LAST_RESORT,
  618.             PARSE_ACCESS|PARSE_HOST|PARSE_PATH|PARSE_PUNCTUATION);
  619.     if (my_home) {
  620.     if (TRACE) fprintf(stderr,
  621.         "HTAccess: Using custom home page %s i.e. address %s\n",
  622.         my_home, ref);
  623.     }
  624.     anchor = (HTParentAnchor*) HTAnchor_findAddress(ref);
  625.     free(ref);
  626.     return anchor;
  627. }
  628.  
  629.  
  630.